package com.lorizz.docrepo.model.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;

import com.lorizz.docrepo.DocrepoException;
import com.lorizz.docrepo.model.Document;
import com.lorizz.docrepo.model.Folder;
import com.lorizz.docrepo.model.Item;
import com.lorizz.docrepo.repository.impl.JcrDocumentRepositoryConstants;

public class FolderImpl extends ItemImpl implements Folder {

    private static final long serialVersionUID = 1L;

    public FolderImpl(Session session, String name) {
        this(session, null, name);
    }

    public FolderImpl(FolderImpl parent, String name) {
        this(parent.getSession(), parent, name);
    }

    public FolderImpl(Session session, FolderImpl parent, String name) {
        this.session = session;
        try {
            Node n;
            if (parent == null)
                n = this.session.getRootNode();
            else
                n = parent.getNode();
            node = n.addNode(name, JcrDocumentRepositoryConstants.NT_FOLDER);
        } catch (RepositoryException e) {
            throw new DocrepoException(e);
        }
    }

    public FolderImpl(Node node) {
        this.node = node;
        try {
            this.session = node.getSession();
        } catch (RepositoryException e) {
            throw new DocrepoException(e);
        }
    }

    @Override
    public Folder createFolder(String name) {
        return new FolderImpl(session, this, name);
    }

    @Override
    public Document createDocument(String name) {
        Document doc = new DocumentImpl(this, name);
        return doc;
    }
    
    @Override
    public Document getDocument(String name) {
        try {
            Node d = node.getNode(name);
            return new DocumentImpl(d);
        } catch (RepositoryException e) {
            throw new DocrepoException(e);
        }
    }

    @Override
    public Document[] getDocuments() {
        List<Document> docs = getSubItems(JcrDocumentRepositoryConstants.NT_DOCUMENT);
        return docs.toArray(new Document[] {});
    }

    @Override
    public Folder[] getFolders() {
        List<Folder> folders = getSubItems(JcrDocumentRepositoryConstants.NT_FOLDER);
        return folders.toArray(new Folder[] {});
    }

    @Override
    public Item[] getItems() {
        List<Item> items = getSubItems(
                JcrDocumentRepositoryConstants.NT_FOLDER,
                JcrDocumentRepositoryConstants.NT_DOCUMENT);
        return items.toArray(new Item[] {});
    }

    @SuppressWarnings("unchecked")
    private <T extends Item> List<T> getSubItems(String... nodeTypes) {
        try {
            List<T> items = new ArrayList<T>();
            NodeIterator i = node.getNodes();
            List<String> nts = Arrays.asList(nodeTypes);
            while (i.hasNext()) {
                Node n = i.nextNode();
                String nt = n.getPrimaryNodeType().getName();
                if (nts.contains(nt)) {
                    if (nt.equals(JcrDocumentRepositoryConstants.NT_FOLDER))
                        items.add((T) new FolderImpl(n));
                    else if (nt
                            .equals(JcrDocumentRepositoryConstants.NT_DOCUMENT))
                        items.add((T) new DocumentImpl(n));
                }
            }
            return items;
        } catch (RepositoryException e) {
            throw new DocrepoException(e);
        }
    }

    @Override
    public String getFullPath() {
        try {
            return node.getPath();
        } catch (RepositoryException e) {
            throw new DocrepoException(e);
        }
    }
}
